Skip to content

feat: persist and restore target height via MetadataStorage#476

Merged
xdustinface merged 1 commit intov0.42-devfrom
feat/persist-last-target
Feb 27, 2026
Merged

feat: persist and restore target height via MetadataStorage#476
xdustinface merged 1 commit intov0.42-devfrom
feat/persist-last-target

Conversation

@xdustinface
Copy link
Collaborator

@xdustinface xdustinface commented Feb 25, 2026

Introduce new functions in MetadataStorage to save/load the last known target height, and integrate it into the block headers manager. This allows the UI to show a more realistic state after restart during sync before connections are established.

Based on:

Summary by CodeRabbit

  • Refactor
    • Block synchronization now persistently stores and retrieves the last target block height.
    • The system saves updates when a new best height is observed, improving resume behavior after restarts and enhancing sync reliability.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 25, 2026

📝 Walkthrough

Walkthrough

The patch adds persistent tracking of the last target block height: new metadata storage API methods, DiskStorageManager implementations, BlockHeadersManager now accepts and stores a metadata storage handle, loads persisted target height on init, and writes updated target height during sync events.

Changes

Cohort / File(s) Summary
Metadata trait & disk impl
dash-spv/src/storage/metadata.rs, dash-spv/src/storage/mod.rs
Add LAST_TARGET_HEIGHT_KEY and new store_last_target_height / load_last_target_height methods to MetadataStorage trait; implement JSON (de)serialization, error handling, and DiskStorageManager plumbing.
Block headers manager core
dash-spv/src/sync/block_headers/manager.rs, dash-spv/src/client/lifecycle.rs
Make BlockHeadersManager generic over M: MetadataStorage, add metadata_storage: Arc<RwLock<M>> field, update constructor to accept metadata_storage, and initialize progress target from persisted height (fallback to tip). Update instantiation call sites.
Sync integration
dash-spv/src/sync/block_headers/sync_manager.rs
Extend SyncManager impl to BlockHeadersManager<H, M> and persist new target height via store_last_target_height when best_height updates are handled.
Coordinator types
dash-spv/src/sync/sync_coordinator.rs
Change Managers field type from Option<BlockHeadersManager<H>> to Option<BlockHeadersManager<H, M>> to propagate metadata generic parameter.
Client storage wiring
dash-spv/src/client/lifecycle.rs
Update BlockHeadersManager::new call sites to pass storage.metadata() alongside header storage and checkpoint manager.

Sequence Diagram(s)

sequenceDiagram
    participant Lifecycle as Lifecycle
    participant BHM as BlockHeadersManager
    participant MS as MetadataStorage
    participant CM as CheckpointManager

    Lifecycle->>BHM: new(header_storage, metadata_storage, checkpoint_manager)
    BHM->>MS: load_last_target_height()
    alt persisted height found
        MS-->>BHM: CoreBlockHeight
        BHM->>BHM: set progress target = persisted height
    else not found / error
        MS-->>BHM: NotFound / Error
        BHM->>BHM: set progress target = tip height
    end
    BHM-->>Lifecycle: initialized

    Note over BHM,MS: during sync updates
    Lifecycle->>BHM: on_network_event(best_height)
    BHM->>MS: store_last_target_height(new_target)
    MS-->>BHM: Result
    BHM-->>Lifecycle: continue sync
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰 I hopped into metadata’s glen,

where heights are kept beyond the when.
I stash the target, snug and bright,
so syncs remember through the night. ✨

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 38.46% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat: persist and restore target height via MetadataStorage' directly and specifically describes the main changes in the PR: adding persistence and restoration of target height using MetadataStorage, which is implemented across multiple files including metadata.rs, manager.rs, and sync_manager.rs.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/persist-last-target

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@xdustinface xdustinface force-pushed the refactor/move-initialization branch from 89ab17e to 8e08c35 Compare February 26, 2026 16:45
@github-actions github-actions bot added the merge-conflict The PR conflicts with the target branch. label Feb 26, 2026
@github-actions
Copy link

This PR has merge conflicts with the base branch. Please rebase or merge the base branch into your branch to resolve them.

@xdustinface xdustinface force-pushed the refactor/move-initialization branch from 8e08c35 to 640c1f8 Compare February 27, 2026 05:48
Base automatically changed from refactor/move-initialization to v0.42-dev February 27, 2026 17:09
@xdustinface xdustinface force-pushed the feat/persist-last-target branch from 9db640f to 3bbea97 Compare February 27, 2026 17:19
@github-actions github-actions bot removed the merge-conflict The PR conflicts with the target branch. label Feb 27, 2026
@xdustinface xdustinface marked this pull request as ready for review February 27, 2026 17:40
@xdustinface xdustinface requested a review from ZocoLini February 27, 2026 17:41
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
dash-spv/src/sync/block_headers/sync_manager.rs (1)

155-156: Consider potential I/O on every peer update.

The target height is persisted on every PeersUpdated event with a new best_height. While this ensures durability, it may result in frequent disk writes during peer discovery. This is acceptable for correctness since atomic writes are used, but consider adding a note or verifying that the write frequency is acceptable in high-churn scenarios.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@dash-spv/src/sync/block_headers/sync_manager.rs` around lines 155 - 156, The
code persists target height on every PeersUpdated event which may cause
excessive I/O; modify the logic around metadata_storage.store_last_target_height
to avoid writing on every update — for example, read the current persisted
height (via metadata_storage) and only call store_last_target_height when
*best_height* is greater than the stored value or when a configured
debounce/interval has elapsed; locate this in sync_manager.rs where PeersUpdated
is handled and update the branch that references
metadata_storage.store_last_target_height to perform the check or debounce
before persisting.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@dash-spv/src/storage/metadata.rs`:
- Around line 19-22: The doc comment for load_last_target_height is incorrect —
update the documentation above the async fn load_last_target_height(&self) ->
StorageResult<CoreBlockHeight> to say "Load the last target height from metadata
storage and restore progress" (or similar wording matching
store_last_target_height) so the comment accurately describes
load_last_target_height's purpose; ensure the doc text mirrors the
store_last_target_height description style for consistency.

---

Nitpick comments:
In `@dash-spv/src/sync/block_headers/sync_manager.rs`:
- Around line 155-156: The code persists target height on every PeersUpdated
event which may cause excessive I/O; modify the logic around
metadata_storage.store_last_target_height to avoid writing on every update — for
example, read the current persisted height (via metadata_storage) and only call
store_last_target_height when *best_height* is greater than the stored value or
when a configured debounce/interval has elapsed; locate this in sync_manager.rs
where PeersUpdated is handled and update the branch that references
metadata_storage.store_last_target_height to perform the check or debounce
before persisting.

ℹ️ Review info

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8d2f76d and 3bbea97.

📒 Files selected for processing (6)
  • dash-spv/src/client/lifecycle.rs
  • dash-spv/src/storage/metadata.rs
  • dash-spv/src/storage/mod.rs
  • dash-spv/src/sync/block_headers/manager.rs
  • dash-spv/src/sync/block_headers/sync_manager.rs
  • dash-spv/src/sync/sync_coordinator.rs

Introduce new functions in `MetadataStorage` to save/load the last known target height, and integrate it into the block headers manager. This allows the UI to show a more realistic state after restart during sync before connections are established.
@xdustinface xdustinface force-pushed the feat/persist-last-target branch from 3bbea97 to 4c5a25d Compare February 27, 2026 17:50
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
dash-spv/src/storage/metadata.rs (1)

103-107: Consider preserving the original error instead of mapping to Corruption.

The Err(e) case wraps any load_metadata failure as StorageError::Corruption, but the underlying error could be an I/O error, permission issue, or other non-corruption failure. This loses error context and may mislead debugging efforts.

♻️ Suggested improvement
             Err(e) => {
-                let error = format!("Failed to load last target height: {}", e);
-                tracing::warn!(error);
-                Err(StorageError::Corruption(error))
+                tracing::warn!("Failed to load last target height: {}", e);
+                Err(e)
             }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@dash-spv/src/storage/metadata.rs` around lines 103 - 107, The current Err(e)
arm wraps any failure as StorageError::Corruption (see the Err(e) block that
formats "Failed to load last target height") which loses the original error
context; change it to preserve or propagate the original error (e.g., return the
underlying error, wrap it in a more appropriate StorageError variant like Io or
include e as the source) instead of unconditionally using
StorageError::Corruption so callers of load_metadata / the function that loads
the last target height can inspect the real cause.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@dash-spv/src/storage/metadata.rs`:
- Around line 103-107: The current Err(e) arm wraps any failure as
StorageError::Corruption (see the Err(e) block that formats "Failed to load last
target height") which loses the original error context; change it to preserve or
propagate the original error (e.g., return the underlying error, wrap it in a
more appropriate StorageError variant like Io or include e as the source)
instead of unconditionally using StorageError::Corruption so callers of
load_metadata / the function that loads the last target height can inspect the
real cause.

ℹ️ Review info

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3bbea97 and 4c5a25d.

📒 Files selected for processing (6)
  • dash-spv/src/client/lifecycle.rs
  • dash-spv/src/storage/metadata.rs
  • dash-spv/src/storage/mod.rs
  • dash-spv/src/sync/block_headers/manager.rs
  • dash-spv/src/sync/block_headers/sync_manager.rs
  • dash-spv/src/sync/sync_coordinator.rs
🚧 Files skipped from review as they are similar to previous changes (1)
  • dash-spv/src/sync/block_headers/sync_manager.rs

@xdustinface xdustinface merged commit 099643b into v0.42-dev Feb 27, 2026
53 checks passed
@xdustinface xdustinface deleted the feat/persist-last-target branch February 27, 2026 18:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants